﻿/// The data structures of the VirtualCity.PlanDescription module mirror exactly those 
/// of the VirtualCity.Plan module, with the only difference that they are immutable,
/// and that they contain no rendering and no physics representations.
/// These data structures are used as the intermediate representation of the plan itself
/// during planning, and refer to the description of the game world. After planning is
/// done, then the plan is transformed into its executable form, of type
/// VirtualCity.Plan.Plan, which for example refers Items instead of ItemDescription,
/// and which refers to the actual game world and its entities that the agent will
/// manipulate as part of its plan.
module VirtualCity.PlanDescription

open Casanova
open Casanova.Utilities
open Casanova.Core
open Casanova.Coroutines
open Casanova.Game
open Casanova.Input
open Casanova.Math
open Casanova.Drawing
open VirtualCity.CityDescription


/// A plan contains a list of steps which represent
/// a series of actions that the agent will perform
/// in order.
/// Actions are represented as a generic parameter, in
/// order to reuse the same definition for multiple layers
/// of planning.
type [<CasanovaEntity>] PlanDescription<'a> = {
  Steps : List<StepDescription<'a>>
} with
  override this.ToString() =
    this.Steps |> Seq.map (string >> (+) ";") |> Seq.fold (+) ""    


/// A step of a plan contains the action for this step,
/// but also the description of what the planner expected 
/// to happen after the execution of the current plan.
/// Actions are represented as a generic parameter, in
/// order to reuse the same definition for multiple layers
/// of planning.
and [<CasanovaEntity>] StepDescription<'a> = {
  Action            : 'a
  Expectations      : StepExpectations
} with 
  override this.ToString() = this.Action.ToString()


/// A lower level action refers to travel only, and it can either be:
/// - walk to the end of a road
/// - board a bus and reach one of its stops
and [<CasanovaEntity>] Layer1ActionDescription = 
  | Walk of Vector2<m>
  //| Board of BusDescription * BusStopDescription * BusStopDescription
  with 
  override this.ToString() = 
    match this with
    | Walk p -> "Walk(" + p.ToString() + ")"
    //| Board (b,s,d) -> "Board(" + b.Number.ToString() + "," + s.Location.ToString() + "->" + d.Location.ToString() + ")"


/// A higher level action can only be to use an item at a given location,
/// and between usages travel is assumed as needed.
and [<CasanovaEntity>] Layer2ActionDescription = 
  | UseAndTravel of Vector2<m> * ItemDescription * int
  with 
  override this.ToString() = 
    match this with
    | UseAndTravel(p,i,_) -> "(" + i.Name + "@" + p.ToString() + ")"


/// An action in the final plan can either be:
/// - walk to the end of a road
/// - board a bus and reach one of its stops
/// - use an item
and [<CasanovaEntity>] ActionDescription = 
  | Walk of Vector2<m>
  //| Board of BusDescription * BusStopDescription * BusStopDescription
  | Use of Vector2<m> * ItemDescription * int
  with 
  override this.ToString() = 
    match this with
    | Walk p -> "Walk(" + p.ToString() + ")"
    //| Board (b,s,d) -> "Board(" + b.Number.ToString() + "," + s.Location.ToString() + "->" + d.Location.ToString() + ")"
    | Use(p,i,_) -> i.Name


/// The expectations of a step in a plan consist of the
/// state of the city and of the agent after the step
/// has been performed. Comparison between the actual
/// state of the city and agent with the expected state
/// allows the planning agent to verify if the plan is
/// proceeding according to the original intentions.
and [<CasanovaEntity>] StepExpectations = {
  City  : CityExpectations
  Agent : AgentExpectations
}


/// The expectations for a city represent what the agent
/// expects from the city given his current knowledge of
/// its "rythms" after the execution of a specified plan.
/// The expected city has a series of buses at given
/// locations, buildings with sets of items in them, roads,
/// and a clock that marks the current time.
and [<CasanovaEntity>] CityExpectations = {
  Buses     : List<Vector2<m> * BusDescription * List<BusStopDescription>>
  Buildings : List<List<ItemDescription> * BuildingDescription>
  Roads     : List<RoadDescription>
  Clock     : ClockDescription
  WalkGraph : WalkGraph
}


and CityDescription = CityExpectations


/// The description for the clock simply holds the current
/// time, with no rules associated.
and [<CasanovaEntity>] ClockDescription = {
  Time    : System.DateTime
}


/// The expectations for an agent represent what the
/// agent expects will happen to himself after the execution 
/// of a specified plan.
and AgentExpectations = CityDescription.AgentDescription
